package cn.com.hhrcw.web;

import cn.com.hhrcw.entity.CvResume;
import cn.com.hhrcw.entity.File;
import cn.com.hhrcw.entity.PiInfo;
import cn.com.hhrcw.entity.SysUser;
import cn.com.hhrcw.mapstruct.CvResumeConvert;
import cn.com.hhrcw.params.CvResumeParams;
import cn.com.hhrcw.params.ResumeFileParams;
import cn.com.hhrcw.service.EnterpriseService;
import cn.com.hhrcw.service.ICvResumeService;
import cn.com.hhrcw.service.IFileService;
import cn.com.hhrcw.service.IPiInfoService;
import cn.com.hhrcw.utils.SubjectUtils;
import cn.com.hhrcw.validator.resume.util.ResumeRequiredValidationUtil;
import cn.com.hhrcw.vo.CvResumeVO;
import cn.com.hhrcw.vo.ResumeInfoVO;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.base.entity.AttributesValueParams;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

/**
 * 简历-简历本历
 *
 * @author jiangdong
 * @since 2020-10-29
 */
@RestController
@Slf4j
@RequestMapping("/personal/v1/cvResume")
@Api(tags = "简历-简历本历")
@Validated
public class CvResumeController extends JeecgController<CvResume, ICvResumeService> {

    @Autowired
    private ICvResumeService cvResumeService;

    @Autowired
    private CvResumeConvert cvResumeConvert;

    @Autowired
    private IPiInfoService piInfoService;

    @Autowired
    EnterpriseService enterpriseService;

    @Autowired
    IFileService fileService;

    /**
     * 简历本历查询
     *
     * @param params 请求参数
     * @return
     */
    @GetMapping(value = "/list")
    @AutoLog("简历-简历本历-分页列表查询")
    @ApiOperation(value = "分页列表查询", notes = "分页列表查询")
    public Result<Page<CvResumeVO>> list(CvResumeParams params, HttpServletRequest request) {
        QueryWrapper<CvResume> queryWrapper = QueryGenerator.initQueryWrapper(cvResumeConvert.toEntity(params), request.getParameterMap());
        queryWrapper.eq("del_flag", false);
        queryWrapper.ne("type", 1);
        if (StringUtils.isBlank(params.getField())) {
            queryWrapper.orderByDesc("create_time");
        } else {
            queryWrapper.orderBy(true, params.getSort(), toUnderlineName(params.getField()));
        }
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        String userId = sysUser.getId();
        queryWrapper.eq("user_id", userId);
        IPage<CvResume> page = cvResumeService.page(params.page(), queryWrapper);
        //分页结果转换器
        Function<CvResume, CvResumeVO> fun = cvResume -> cvResumeConvert.toVO(cvResume);

        return Result.ok((Page) page.convert(fun));
    }

    /**
     * 根据id查询
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/queryById")
    @ApiOperation(value = "根据id查询", notes = "根据id查询")
    @PermissionData
    public Result<CvResumeVO> queryById(String id) {
        CvResume cvResume = cvResumeService
            .lambdaQuery()
            .eq(CvResume::getId, id)
            .eq(CvResume::getDelFlag, false)
            .one();
        if (cvResume == null) {
            throw new JeecgBootException("数据不存在");
        }
        return Result.ok(cvResumeConvert.toVO(cvResume));
    }

    /**
     * 简历本历添加
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/add")
    @AutoLog("简历-简历本历-添加")
    @ApiOperation(value = "添加", notes = "添加")
    public Result<?> add(@RequestBody @Valid CvResumeParams params) {

        //创建空简历本例
        CvResumeVO vo = new CvResumeVO();
        boolean updated = false;
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        //编辑
        if (StringUtils.isNotBlank(params.getId())) {
            CvResume resume = cvResumeService.getById(params.getId());
            String enclosureId = resume.getEnclosureId();
            if (StringUtils.isNotBlank(enclosureId)) {
                enclosureId += params.getEnclosureId() + ",";
            } else {
                enclosureId = params.getEnclosureId() + ",";
            }
            params.setEnclosureId(enclosureId);
            CvResume cvResume = cvResumeConvert.toEntity(params);
            cvResume.setUpdateBy(sysUser.getId());
            cvResume.setUpdateTime(DateUtil.date());
            PiInfo piInfo = piInfoService.lambdaQuery().eq(PiInfo::getUserId, sysUser.getId()).eq(PiInfo::getDelFlag, false).one();
            cvResume.setBrowseCount(0);
            if (resume.getLanType() == 1) {
                cvResume.setResumeName("My resume");
            } else {
                cvResume.setResumeName(piInfo.getName() + "的中文简历");
            }

            updated = cvResumeService.updateById(cvResume);
        } else {
            CvResume cvResume = cvResumeConvert.toEntity(params);
            if (params.getType() == 1) {
                LambdaUpdateWrapper<CvResume> wrapper = Wrappers.lambdaUpdate();
                wrapper.eq(CvResume::getUserId, sysUser.getId())
                    .eq(CvResume::getType, 1)
                    .eq(CvResume::getDelFlag, false);
                List<CvResume> list = cvResumeService.list(wrapper);
                if (!CollectionUtils.isEmpty(list)) {
                    return Result.error("已有附件简历，请先删除后再上传");
                }

                PiInfo piInfo = piInfoService.lambdaQuery().eq(PiInfo::getUserId, sysUser.getId()).eq(PiInfo::getDelFlag, false).one();
                cvResume.setResumeName(piInfo.getName() + "的附件简历");
            }

            if (params.getLanType() == 0) {
                LambdaUpdateWrapper<CvResume> wrapper = Wrappers.lambdaUpdate();
                wrapper.eq(CvResume::getLanType, params.getLanType()).eq(CvResume::getUserId, sysUser.getId())
                    .eq(CvResume::getType, params.getType())
                    .eq(CvResume::getDelFlag, false);
                List<CvResume> list = cvResumeService.list(wrapper);
                if (!CollectionUtils.isEmpty(list)) {
                    return Result.error("已有简历，无需再次添加");
                }
            } else {
                LambdaUpdateWrapper<CvResume> wrapper = Wrappers.lambdaUpdate();
                wrapper.eq(CvResume::getLanType, params.getLanType()).eq(CvResume::getUserId, sysUser.getId())
                    .eq(CvResume::getType, 0)
                    .eq(CvResume::getDelFlag, false);
                List<CvResume> list = cvResumeService.list(wrapper);
                if (!CollectionUtils.isEmpty(list)) {
                    return Result.error("已有简历，无需再次添加");
                }
                cvResume.setResumeName("My resume");
            }

            if (!params.getUserId().equals(sysUser.getId())) {
                return Result.error("信息填写错误");
            }

            cvResume.setCreateBy(sysUser.getId());
            cvResume.setCreateTime(DateUtil.date());
            cvResume.setDelFlag(false);
            String couponId = IdUtil.getSnowflake(0, 0).nextIdStr();
            cvResume.setId(couponId);
            cvResume.setBrowseCount(0);
            cvResume.setUpdateTime(DateUtil.date());
            cvResume.setUpdateBy(sysUser.getId());
            updated = cvResumeService.save(cvResume);
            vo = cvResumeConvert.toVO(cvResume);
        }
        if (updated) {
            String resumeInfo = cvResumeService.getResumeInfo(sysUser.getId(), params.getLanType(), null);
            String resumePdfInfo = cvResumeService.getResumeInfoPDF(sysUser.getId(), params.getLanType(), null);
        }
        return updated ? Result.ok(vo) : Result.error("添加失败");
    }

    /**
     * 简历本历编辑
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping(value = "/edit")
    @AutoLog("简历-简历本历-编辑")
    @ApiOperation(value = "编辑", notes = "编辑")
    public Result<?> edit(@RequestBody @Valid CvResumeParams params) {
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        if (StringUtils.isBlank(params.getId())) {
            return Result.error("id必填");
        }
        CvResume resume = cvResumeService.getById(params.getId());
        String enclosureId = resume.getEnclosureId();
        if (StringUtils.isNotBlank(enclosureId)) {
            enclosureId += params.getEnclosureId() + ",";
        } else {
            enclosureId = params.getEnclosureId() + ",";
        }
        params.setEnclosureId(enclosureId);
        CvResume cvResume = cvResumeConvert.toEntity(params);
        cvResume.setUpdateBy(sysUser.getId());
        cvResume.setUpdateTime(DateUtil.date());
        if (cvResume.getResumeType() == null) {
            cvResume.setResumeType(resume.getResumeType());
        }
        PiInfo piInfo = piInfoService.lambdaQuery().eq(PiInfo::getUserId, sysUser.getId()).eq(PiInfo::getDelFlag, false).one();
        if (resume.getLanType() == 1) {
            cvResume.setResumeName("My resume");
        } else {
            String resumeName = StrUtil.format("{}的{}中文简历", piInfo.getName(), cvResume.getResumeType() == 2 ? "校招" : "");
            cvResume.setResumeName(resumeName);
        }

        boolean updated = cvResumeService.updateById(cvResume);

        return updated ? Result.ok() : Result.error("编辑失败");
    }

    /**
     * 附件删除
     *
     * @param
     * @return
     */
    @PostMapping(value = "/file/delete")
    @AutoLog("简历附件文件删除")
    @ApiOperation(value = "附件文件删除", notes = "附件文件删除")
    public Result fileDelete(@RequestBody ResumeFileParams params) {
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        LambdaUpdateWrapper<CvResume> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.in(CvResume::getId, params.getId())
            .set(CvResume::getDelFlag, false);
        CvResume serviceOne = cvResumeService.getOne(updateWrapper);
        if (null == serviceOne) {
            throw new JeecgBootException("数据不存在");
        }
        if (!sysUser.getId().equals(serviceOne.getUserId())) {
            return Result.error("信息错误");
        }
        String newId = "";
        String enclosureId = serviceOne.getEnclosureId();
        if (StringUtils.isNotBlank(enclosureId)) {
            String[] split = enclosureId.split(",");
            List<String> tbList = new ArrayList<>(Arrays.asList(split));
            for (int i = 0; i < tbList.size(); i++) {
                String s = tbList.get(i);
                if (s.equals(params.getEnclosureId())) {
                    tbList.remove(s);
                }
            }
            //            for (String s : tbList) {
            //
            //            }
            if (CollectionUtils.isNotEmpty(tbList)) {
                for (String s : tbList) {
                    newId += s + ",";
                }
            }

        }
        serviceOne.setEnclosureId(newId);
        boolean update = cvResumeService.updateById(serviceOne);

        return update ? Result.ok() : Result.error("删除失败");
    }

    /**
     * 简历删除
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/delete")
    @AutoLog("简历-简历本历-批量删除")
    @ApiOperation(value = "批量删除", notes = "批量删除")
    public Result delete(String[] id) {
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        LambdaUpdateWrapper<CvResume> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.in(CvResume::getId, id)
            .set(CvResume::getDelFlag, true)
            .set(CvResume::getUpdateBy, sysUser.getUsername())
            .set(CvResume::getUpdateTime, DateUtil.date());

        boolean deleted = cvResumeService.update(updateWrapper);
        return deleted ? Result.ok() : Result.error("删除失败");
    }

    /**
     * 属性值是否重复
     *
     * @return
     */
    @Override
    @GetMapping("/propertyRepeat")
    @ApiOperation(value = "属性值是否重复", notes = "属性值是否重复")
    public Result propertyIsRepeat(@Valid AttributesValueParams params) {
        return super.propertyIsRepeat(params);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param params
     */
    @SneakyThrows
    @GetMapping(value = "/exportXls")
    @ApiOperation(value = "导出excel", notes = "导出excel")
    public Result exportXls(HttpServletRequest request, CvResumeParams params) {
        CvResume cvResume = cvResumeConvert.toEntity(params);
        cvResume.setDelFlag(false);
        QueryWrapper<CvResume> queryWrapper = QueryGenerator.initQueryWrapper(cvResume, request.getParameterMap());
        List<CvResume> data = cvResumeService.list(queryWrapper);
        ExportParams exportParams = new ExportParams("简历-简历本历", "简历-简历本历");
        String url = super.exportXls(exportParams, CvResumeVO.class, cvResumeConvert.toVO(data));
        return Result.ok((Object) url);
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping(value = "/importExcel")
    @ApiOperation(value = "通过excel导入数据", notes = "通过excel导入数据")
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, CvResume.class);
    }

    /**
     * 根据简历id查看在线简历详情
     *
     * @param resumeId 简历id
     * @return
     */
    @GetMapping("/getResumeInfoByUserId")
    public Result<ResumeInfoVO> getResumeInfo(String resumeId) {
        ResumeInfoVO vo = enterpriseService.getResumeInfo(resumeId);
        return Result.ok(vo);
    }

    /**
     * 根据简历id更新在线简历详情
     *
     * @param resumeId 简历id
     * @return
     */
    @GetMapping("/updateResumeInfo")
    public Result<?> updateResumeInfo(String resumeId) {
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        CvResume cvResume = cvResumeService
            .lambdaQuery()
            .eq(CvResume::getId, resumeId)
            .eq(CvResume::getDelFlag, false)
            .one();
        if (cvResume == null) {
            throw new JeecgBootException("数据不存在");
        }
        cvResume.setPdfPathEn("");
        cvResume.setPdfPath("");
        cvResume.setWordPathEn("");
        cvResume.setWordPath("");
        service.updateById(cvResume);

        //2022年4月8日17:46:08 zhf 增加，保证html是最新的
        String path = cvResumeService.getResumeInfoPDF(cvResume.getUserId(), 0, null);
        log.info("生成html {}", path);

        return Result.ok();
    }

    /**
     * 根据简历id更新在线简历详情(英文简历)
     * //2022年4月11日16:05:08 yy 增加
     *
     * @param resumeId 简历id
     * @return
     */
    @GetMapping("/updateResumeInfoEn")
    public Result<?> updateResumeInfoEn(String resumeId) {
        SysUser sysUser = (SysUser) SubjectUtils.getSubject();
        CvResume cvResume = cvResumeService
            .lambdaQuery()
            .eq(CvResume::getId, resumeId)
            .eq(CvResume::getDelFlag, false)
            .one();
        if (cvResume == null) {
            throw new JeecgBootException("数据不存在");
        }
        cvResume.setPdfPathEn("");
        cvResume.setPdfPath("");
        cvResume.setWordPathEn("");
        cvResume.setWordPath("");
        service.updateById(cvResume);
        //2022年4月11日16:05:08 yy 增加
        String path = cvResumeService.getResumeInfoPDF(cvResume.getUserId(), 1, null);
        log.info("生成html {}", path);
        return Result.ok();
    }

    /**
     * 在线预览简历，二进制流形式
     *
     * @param userId   用户id
     * @param langType 语言类型0中文1英文
     * @param type     0在线简历1附件简历
     */
    @GetMapping("/getResumeBriny")
    public ResponseEntity getResumeBriny(String userId, Integer langType, Integer type, HttpServletResponse response) throws IOException {
        String url = "";
        if (type != null && type == 1) {
            CvResume cvResume = cvResumeService.lambdaQuery().eq(CvResume::getDelFlag, false).eq(CvResume::getUserId, userId)
                .eq(CvResume::getType, 1).one();
            if (cvResume != null) {
                File file = fileService.getById(cvResume.getFileId());
                url = file.getFilePath();
            }
            java.io.File file = new java.io.File(url);
            byte[] bytes = new byte[0];
            if (file.exists()) {
                bytes = FileUtil.readBytes(file);
            }
            return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_PDF)
                .contentLength(bytes.length)
                .body(new ByteArrayResource(bytes));
        } else {
            CvResume cvResume = cvResumeService.lambdaQuery().eq(CvResume::getDelFlag, false).eq(CvResume::getUserId, userId)
                .eq(CvResume::getType, 0).eq(CvResume::getLanType, langType).one();
            if (cvResume != null) {
                //中文
                if (langType == 0) {
                    url = org.apache.commons.lang.StringUtils.isNotBlank(cvResume.getPdfPath()) ? cvResume.getPdfPath() : cvResumeService.getResumeInfoPDF(cvResume.getUserId(), 0, null);
                } else {
                    url = org.apache.commons.lang3.StringUtils.isNotBlank(cvResume.getPdfPathEn()) ? cvResume.getPdfPathEn() : cvResumeService.getResumeInfoPDF(cvResume.getUserId(), 1, null);
                }
            }
            java.io.File file = new java.io.File(url);
            String html = "";
            if (file.exists()) {
                html = FileUtil.readString(file, StandardCharsets.UTF_8);
            }
            return ResponseEntity.ok()
                .contentType(MediaType.TEXT_HTML)
                .contentLength(file.length())
                .body(html);
        }
    }

    /**
     * 下载简历
     *
     * @param id
     * @param response
     * @throws IOException
     */
    @GetMapping("/download")
    public void download(String id, HttpServletResponse response) throws IOException {
        ServletOutputStream out = response.getOutputStream();
        try {
            if (StringUtils.isBlank(id)) {
                throw new JeecgBootException("下载异常");
            }
            CvResume resume = cvResumeService.lambdaQuery().eq(CvResume::getId, id).one();
            Integer type = resume.getType();
            java.io.File file = null;
            String fileName = "简历";
            byte[] bytes = new byte[0];
            if (type == 0) {
                // 在线简历
                Integer lanType = resume.getLanType();
                bytes = this.cvResumeService.getResumeInfo(null, resume.getUserId(), lanType);
                if (lanType == 0) {
                    fileName = resume.getResumeType() == 1 ? "社招简历" : "校招简历";
                } else {
                    // 英文
                    fileName = "English Resume";
                }
                fileName += ".docx";
            } else {
                fileName = "附件简历";
                cn.com.hhrcw.entity.File fileEntity = fileService.getById(resume.getFileId());
                if (fileEntity != null) {
                    PiInfo piInfo = piInfoService.lambdaQuery().eq(PiInfo::getUserId, resume.getUserId()).one();
                    fileName = piInfo.getName() + "附件简历." + fileEntity.getFileLastName();
                    bytes = FileUtil.readBytes(fileEntity.getFilePath());
                }
            }
            String downloadFilename = URLEncoder.encode(fileName, "UTF-8");
            // 指明response的返回对象是文件流
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            // 设置在下载框默认显示的文件名
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + downloadFilename);
            response.setHeader(HttpHeaders.CONTENT_LENGTH, Convert.toStr(bytes.length));
            out.write(bytes);
            out.flush();
        } catch (Exception e) {
            log.error("下载简历错误" + e.getMessage(), e);
            out.write("简历下载失败".getBytes(StandardCharsets.UTF_8));
            out.flush();
        } finally {
            IoUtil.close(out);
        }
    }

    @Autowired
    private ResumeRequiredValidationUtil resumeRequiredValidationUtil;

    /**
     * 根据id检查简是否满足投递需求
     *
     * @param id 数据id
     * @return
     */
    @GetMapping(value = "/check")
    @PermissionData
    public Result check(String id) {
        CvResume cvResume = cvResumeService
            .lambdaQuery()
            .eq(CvResume::getId, id)
            .eq(CvResume::getDelFlag, false)
            .one();
        if (cvResume == null) {
            throw new JeecgBootException("数据不存在");
        }
        Result r = resumeRequiredValidationUtil.isValid(id, false);
        if (r.isSuccess()) {
            return Result.ok("");
        } else {
            return r;
        }

    }
}
